﻿using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace IpRange;

public class ParseIpCidr
{
    private static readonly JsonSerializerOptions Options = new(JsonSerializerDefaults.Web)
    {
        WriteIndented = true,
        DefaultBufferSize = 1024 * 64,
        PropertyNameCaseInsensitive = true
    };

    public async Task Parse(string inputPath, string outputPath)
    {
        const int bufferSize = 8192;
        await using FileStream inputStream = new(inputPath, FileMode.Open, FileAccess.Read);
        await using FileStream outStream = new(outputPath, FileMode.Create, FileAccess.Write, FileShare.None,
            bufferSize: bufferSize, useAsync: true);

        await using StreamWriter streamWriter = new(outStream);
        StringBuilder buffer = new();

        AutonomousSystemNumberDetails? details =
            await JsonSerializer.DeserializeAsync<AutonomousSystemNumberDetails>(inputStream, Options);

        if (details?.Ranges != null)
        {
            foreach (string range in details.Ranges)
            {
                // 解析CIDR
                string[] cidrParts = range.Split('/');
                IPAddress ipAddress = IPAddress.Parse(cidrParts[0]);
                int prefix = int.Parse(cidrParts[1]);

                // 转换为32位整数
                byte[] ipBytes = ipAddress.GetAddressBytes();
                uint ipUint = ((uint)ipBytes[0] << 24) | ((uint)ipBytes[1] << 16) | ((uint)ipBytes[2] << 8) |
                              (uint)ipBytes[3];

                // 计算地址范围
                uint mask = prefix == 0 ? 0 : 0xFFFFFFFFu << (32 - prefix);
                uint network = ipUint & mask;
                uint broadcast = network | (~mask);

                // 生成所有IP地址
                for (uint current = network; current <= broadcast; current++)
                {
                    // 直接构建IP字符串（比使用IPAddress对象快3倍）
                    buffer.AppendLine(
                        $"{(current >> 24) & 0xFF}." +
                        $"{(current >> 16) & 0xFF}." +
                        $"{(current >> 8) & 0xFF}." +
                        $"{current & 0xFF}");

                    // 缓冲达到阈值时异步写入
                    if (buffer.Length < bufferSize) continue;
                    await streamWriter.WriteAsync(buffer.ToString());
                    buffer.Clear();
                }

                // 写入剩余缓冲内容
                if (buffer.Length > 0)
                {
                    await streamWriter.WriteAsync(buffer.ToString());
                }
            }
        }
    }
}